#pragma once

#include <iostream>
#include <string>
#include <memory>
#include <poll.h>
#include "Logger.hpp"
#include "InetAddr.hpp"
#include "Socket.hpp"

const static int gsize = sizeof(fd_set) * 8;
const static int gdefaultfd = -1;

// TCP server
class PollServer
{
public:
    PollServer(uint16_t port)
        : _listensock(std::make_unique<TcpSocket>())
    {
        _listensock->BuildlistenSocketMethod(port);
        for (int i = 0; i < gsize; i++)
        {
            fd_array[i].fd = gdefaultfd;
            fd_array[i].events = fd_array[i].revents = 0;
        }
        fd_array[0].fd = _listensock->SockFd();
        fd_array[0].events = POLLIN;
    }
    // 1. 新连接到来 && 连接断开也属于新事件到来
    // 2. 给server发送数据，让指定的fd就绪，也是新事件到来！
    void Accepter()
    {
        // 获取新连接了
        InetAddr clientadddr;
        // "拷贝"
        // 会不会被阻塞呢？不会！！，因为select已经告诉我了，已经就绪了！
        int sockfd = _listensock->Accept(&clientadddr);
        if (sockfd > 0)
        {
            LOG(Loglevel::INFO) << "get new sockfd: " << 
                sockfd << ", client addr: " << clientadddr.ToString();

            // 可以直接调用recv(sockfd ...) 吗？不能！
            // 那应该怎么办？sockfd 托管给select！！
            // 如何把新的sockfd托管给select? 只要把新的sockfd放入辅助数组中即可！
            int pos = 0;
            for (; pos < gsize; pos++)
            {
                if (fd_array[pos].fd == gdefaultfd)
                {
                    fd_array[pos].fd = sockfd;
                    fd_array[pos].events = POLLIN; //| POLLOUT;
                    break;
                }
            }
            if (pos == gsize)
            {
                LOG(Loglevel::WARNING) << "server is full!";
                close(sockfd);
                // 扩容
            }
        }
    }
    void Recver(int index)
    {
        int sockfd = fd_array[index].fd;
        char buffer[1024];
        // 这里读取，会不会阻塞？不会！
        // 这里的读取有问题！
        ssize_t n = recv(sockfd, buffer, sizeof(buffer), 0);
        if(n > 0)
        {
            buffer[n] = 0;
            std::cout << "client say@ " << buffer << std::endl;
            std::string echo_string = "server echo# ";
            echo_string += buffer;
            send(sockfd, echo_string.c_str(), echo_string.size(), 0); // ?
        }
        else if(n == 0)
        {
            LOG(Loglevel::INFO) << "client quit, me too: " << fd_array[index].fd;
            fd_array[index].fd = gdefaultfd;
            fd_array[index].events = fd_array[index].revents = 0;
            close(sockfd);
        }
        else
        {
            LOG(Loglevel::WARNING) << "recv error: " << fd_array[index].fd;
            fd_array[index].fd = gdefaultfd;
            fd_array[index].events = fd_array[index].revents = 0;
            close(sockfd);
        }
    }
    void EventDispatcher()
    {
        LOG(Loglevel::INFO) << "fd就绪,有新事件到来";

        for (int i = 0; i < gsize; i++)
        {
            if (fd_array[i].fd == gdefaultfd)
            {
                continue;
            }

            // 读事件就绪
            if (fd_array[i].revents & POLLIN)
            {
                if (fd_array[i].fd == _listensock->SockFd())
                {
                    Accepter(); // 连接管理器
                }
                else{
                    Recver(i);   // IO处理器
                }
            }
            // else if(FD_ISSET(fd_array[i], &wrfds))
            // {

            // }
        }
    }
    void Run()
    {
        while (true)
        {
            int timeout = -1;
            int n = poll(fd_array, gsize, timeout);
            switch (n)
            {
            case 0:
                LOG(Loglevel::DEBUG) << "timeout...: ";
                break;
            case -1:
                LOG(Loglevel::ERROR) << "poll error";
                break;
            default:
                // 一定有事件就绪了, 就绪事件，派发到不同的处理模块
                EventDispatcher();
                break;
            }
        }
    }

    ~PollServer()
    {
    }

private:
    std::unique_ptr<Socket> _listensock;
    struct pollfd fd_array[gsize];
    // struct pollfd *fd_array;
};